package org.datavis.axis;

import java.util.ArrayList;
import org.datavis.chart.Chart;
import org.datavis.data.Data;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.DrawFilter;
import android.graphics.Paint;
import android.graphics.PaintFlagsDrawFilter;
import android.graphics.Rect;
import android.view.View;

/**
 * @author Benjamin Vogler
 * @version 1.0
 * abstract
 * HorizontalAxis is used to draw the horizontal axis in charts
 * 
 */
public abstract class HorizontalAxis extends View {
	
	protected Chart chart = null;
	protected Canvas canvas = null;
	protected Bitmap bitmap = null;
	protected int origin = 0;
	protected Data data = null;
	protected int decimals = 0;
	protected ArrayList<Integer> entryPositions = new ArrayList<Integer>();
	protected float fontSize = 0.f;
	protected int spacer = 0;
	protected Paint mPaint = null;
	

	public HorizontalAxis(Context context, Chart chart) {
		super(context);
		this.chart = chart;
		// TODO Auto-generated constructor stub
	}
	
	 protected void onSizeChanged(int w, int h, int oldw, int oldh) {
		 if (bitmap != null) {
			 bitmap .recycle();
		 }
		 if(w > 0 && h > 0)
		 {
			 canvas = new Canvas();
			 DrawFilter drawFilter = new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG);
			 canvas.setDrawFilter(drawFilter);
			 bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
			 canvas.setBitmap(bitmap);
		 }
	 }
	 
	 public void destroy() {
		 if (bitmap != null) {
			 bitmap.recycle();
		 }
	 }
	
	 @Override
	 public void onDraw(Canvas c) {
		 
		super.onDraw(c);
		canvas.drawColor(0, android.graphics.PorterDuff.Mode.CLEAR);		 
		mPaint = new Paint(); 
		mPaint.setColor(0xFF000000);  
		mPaint.setStyle(Paint.Style.FILL);
		mPaint.setStrokeWidth(0.1f);
		mPaint.setTextSize(chart.getFontSize());
		mPaint.setTypeface(chart.getFontType());
		mPaint.setTextAlign(Paint.Align.CENTER);
	 	
		data = chart.getData();
		fontSize = chart.getFontSize();
		
	 	if(data != null)
	 	{
	 		//draw descriptions
	 		if(chart.isDrawHDescription())
	 		{
	 			//calculate descriptions
	 			int entryWidth = calculateWidth(data.getValuesPerEntry(), 1);
	 			//draw descriptions
	 			if(chart.gethAxisDescModus() == Chart.ANGLED)
				{
	 				drawAngledTicks(entryWidth);
				}
				else if(chart.gethAxisDescModus() == Chart.STAGGERED)
				{
					drawStaggeredTicks(entryWidth);
				}
				else if(chart.gethAxisDescModus() == Chart.STRAIGHT)
				{
					drawStraightTicks(entryWidth);
				}
	 			
	 		}
	 		
	 		//draw title
	 		if(chart.gethAxisTitle() != "")
	 		{
	 			//draw title
	 			drawTitle();
	 		}
	 	} 	

		//draw Axis
	 	canvas.drawLine(spacer, 0, this.getWidth(), 0, mPaint);
       	 	
	 	c.drawBitmap(bitmap, 
			new Rect(0,0,bitmap.getWidth(),bitmap.getHeight()), 
			new Rect(0,0,bitmap.getWidth(),bitmap.getHeight()), null);
	 }
 
	/**
	 * abstract method
	 * calculates the distance between chart entries in pixel
	 * 
	 * @param valuesPerEntry the number of values in the value sequence of the chart
	 */
	protected abstract void calculateEntryPositions(int valuesPerEntry);
	
	protected int calculateWidth(double maxValue, double value){
	 	int width = 0;
	 	 
	 	width = (int)((this.getWidth() - spacer) * (value/maxValue));
	 	
	 	return width;
	 }

	public void setSpacer(int spacer) {
		this.spacer = spacer;
	}
	
	//draw angled descriptions
	protected void drawAngledTicks(int entryWidth) {	
		canvas.save();
        canvas.rotate(-45, 0, 0);
        mPaint.setTextAlign(Paint.Align.RIGHT);
        mPaint.setTextSize(fontSize);
        
        float value = 0;
        int t = 0;
        
        for (int i = 0; i < data.getDescriptions().size(); i++)
		{
        	value = (entryWidth * i) + (entryWidth/2) + spacer;
        	t = (int)((Math.pow(2,0.5)/2) * value);
			canvas.drawText(data.getDescriptions().get(i), t-3 , t +10, mPaint);
		}        
        canvas.restore(); 
	}
	
	//draw staggered descriptions
	protected void drawStaggeredTicks(int entryWidth) {
		mPaint.setTextAlign(Paint.Align.CENTER);
		mPaint.setTextSize(fontSize);
		
		float value = 0;
		float t = 0;
		
		for (int i = 0; i < data.getDescriptions().size(); i++)
		{
			value = (entryWidth * i) + (entryWidth/2) + spacer;
			if(i%2 != 0)
				t=	(float)(fontSize * 2.4);
			else
				t = (float)(fontSize * 1.2);
			canvas.drawText(data.getDescriptions().get(i), value , t, mPaint);
		}        
	}

	//draw straight descriptions
	protected void drawStraightTicks(int entryWidth) {
		mPaint.setTextAlign(Paint.Align.CENTER);
		mPaint.setTextSize(fontSize);
		
		float value = 0;
		float t = 0;
		
		for (int i = 0; i < data.getDescriptions().size(); i++)
		{
			value = (entryWidth * i) + (entryWidth/2) + spacer;
			t = (float)(fontSize * 1.2);
			canvas.drawText(data.getDescriptions().get(i), value , t, mPaint);
		}        
	}
	
	//draw title
	protected void drawTitle() {
	 	float py = this.getHeight() - (fontSize/3);
        float px = spacer + (this.getWidth() - spacer)/2.0f;       
        mPaint.setTextAlign(Paint.Align.CENTER);
        mPaint.setTextSize(fontSize);
        canvas.drawText(chart.gethAxisTitle(), px, py, mPaint);
	}
}
